package org.orbroker
import org.orbroker.callback.ExecutionCallback
import java.sql.{ SQLWarning, SQLException }

private[orbroker] trait JdbcType[-T] {
  def close(t: T)
  def getWarnings(t: T): SQLWarning
}

private[orbroker] object JdbcCloser {
  implicit object JdbcConnection extends JdbcType[java.sql.Connection] {
    def close(conn: java.sql.Connection) = conn.close()
    def getWarnings(conn: java.sql.Connection) = conn.getWarnings
  }
  implicit object JdbcResultSet extends JdbcType[java.sql.ResultSet] {
    def close(rs: java.sql.ResultSet) = rs.close()
    def getWarnings(rs: java.sql.ResultSet) = rs.getWarnings
  }
  implicit object JdbcStatement extends JdbcType[java.sql.Statement] {
    def close(ps: java.sql.Statement) = ps.close()
    def getWarnings(ps: java.sql.Statement) = ps.getWarnings
  }

  def checkWarningsAndClose[T](jdbc: T, callback: ExecutionCallback)(implicit exe: JdbcType[T]) {
    try {
      handleWarning(callback, exe.getWarnings(jdbc))
    } catch {
      case e: SQLException ⇒ // Ignore
    } finally {
      exe.close(jdbc)
    }
  }

  @scala.annotation.tailrec
  private def handleWarning(callback: ExecutionCallback, warning: java.sql.SQLWarning) {
    if (warning != null) {
      callback.onWarning(warning)
      handleWarning(callback, warning.getNextWarning)
    }
  }

}